/**
 * @author 0283000115
 * @date 2018年6月19日-下午3:54:26
 */
package com.zte.claa.inficombo.csa.app.service.svrmoni;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.zte.claa.inficombo.csa.app.util.JsonUtils;

/**
 * @author 0283000115
 *
 */

@Service("ServerMonitorService")
@Lazy(false)
public class ServerMonitorService implements InitializingBean, DisposableBean {	
	// 日志
	private Logger logger = LoggerFactory.getLogger(ServerMonitorService.class);
	
	@Autowired
	private StringRedisTemplate redisStrTemplate;
	
	// application.properties文件中配置. redis.hashkey.svrnodestate=k_svrnode_state_moni	
	@Value("${redis.hashkey.svrnodestate}")
	private String redisSvrNodeStateKey;
	
	@Value("${server.port}")
	private int curSvrPort;
	
	@Value("${svrnodestate.report.interval}")
	private long svrNodeStateRptInterval;
	
	@Value("${svrnodestate.svr.index}")
	private int curSvrNodeIndex;
	
	// web服务进程状态上报定时器.
	private ScheduledExecutorService svrStateRptExecutor = null;
	// 本服务初次启动时间戳.
	private long svrStartTime = 0;
	// redis-nodestate-key访问bound
	private BoundHashOperations<String, Object, Object> redisHashOp = null;
	
	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		this.svrStartTime = 0;
		this.createRedisHsOp();
		this.svrStateRptExecutor = Executors.newScheduledThreadPool(1);
		Runnable r = new Runnable() {
			@Override
			public void run() {
				reportSvrStateToRedis();
			}
		};
		// 延迟10秒启动，每60秒上报一次.
		this.svrStateRptExecutor.scheduleWithFixedDelay(r, 10, svrNodeStateRptInterval, TimeUnit.SECONDS);
		logger.info("Server state report woker start with interval(s)="+svrNodeStateRptInterval);
	}
	
	/**
	 * 
	 */
	private boolean createRedisHsOp(){
		try{
			this.redisHashOp = this.redisStrTemplate.boundHashOps(this.redisSvrNodeStateKey);
			// 移除key的过期时间（永久有效）
			this.redisHashOp.persist();
			return true;
		}catch(Exception e){
			logger.warn("Redis key bound failed:"+this.redisSvrNodeStateKey+", err="+e.getMessage());
			this.redisHashOp = null;
			return false;
		}
	}
	
	/**
	 * 1.初始化初次上报时间。
	 * 2.ip地址和端口获取，服务名配置；
	 * 3.数据上报；
	 */
	private void reportSvrStateToRedis(){
		if(this.redisHashOp == null){
			logger.debug("Redis server connect failed!");
			return;
		}
		try {
			if(this.svrStartTime == 0){
				this.svrStartTime = System.currentTimeMillis();
			}
			ServerNode redisSn = new ServerNode();
			redisSn.setIpaddr(this.getCurSvrIp());
			redisSn.setSvrport(this.curSvrPort);
			redisSn.setStarttime(svrStartTime);
			redisSn.setRpttime(System.currentTimeMillis());
			redisSn.setSvrtype(ServerNode.SVR_TP_CSA);
			redisSn.setRunstate(ServerNode.RUN_ST_ONLINE);
			// redisSn.setSvrid(ServerNode.parseSvrNodeType(ServerNode.SVR_TP_CSA)+"."+this.curSvrNodeIndex);
			// 以ip:port作为svrnode在redis中的ID...
			redisSn.setSvrid(redisSn.getIpaddr()+":"+this.curSvrPort);
			redisSn.setSvrname("业务适配服务器["+this.curSvrNodeIndex+"]");
			redisSn.setSvrInstanceNo(this.curSvrNodeIndex);
			this.redisHashOp.put(redisSn.getSvrid(), JsonUtils.toJson(redisSn));	
			logger.debug("Report current server state ok!");
		} catch (Throwable e) {
			logger.error("Report current server state failed!", e);
		}
	}
	
	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.DisposableBean#destroy()
	 */
	@Override
	public void destroy() throws Exception {
		if(this.svrStateRptExecutor != null){
			this.svrStateRptExecutor.shutdown();
			this.svrStateRptExecutor = null;
		}
	}
	
	/**
	 * 获取本机IP地址
	 * 
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	private String getCurSvrIp() {
		try {
			InetAddress candidateAddress = null;
			// 遍历所有的网络接口
			for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
				NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
				// 在所有的接口下再遍历IP
				for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
					InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
					// 排除loopback类型地址
					if (inetAddr.isLoopbackAddress()) {
						continue;
					}
					if (inetAddr.isSiteLocalAddress()) {
						// 如果是site-local地址，就是它了
						return inetAddr.getHostAddress();
					} else if (candidateAddress == null) {
						// site-local类型的地址未被发现，先记录候选地址
						candidateAddress = inetAddr;
					}
				}
			}
			if (candidateAddress != null) {
				return candidateAddress.getHostAddress();
			}
			// 如果没有发现 non-loopback地址.只能用最次选的方案
			InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
			return jdkSuppliedAddress.getHostAddress();
		} catch (Exception e) {
			logger.error("Get local host ip failed: "+e.getMessage());
		}
		return "127.0.0.1";
	}
	
}
